package com.yyfax.pay.common.aspect;
import java.lang.reflect.Method;
import java.util.Iterator;
import java.util.Set;

import javax.validation.ConstraintViolation;
import javax.validation.Validation;
import javax.validation.executable.ExecutableValidator;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.reflect.MethodSignature;
import org.hibernate.validator.HibernateValidator;
import org.hibernate.validator.parameternameprovider.ParanamerParameterNameProvider;

import com.yyfax.framework.exception.YYException;
import com.yyfax.pay.common.enums.PayRspCodeEnum;

public class ValidatorAspect {

    private ExecutableValidator executableValidator;

    public ValidatorAspect() {
        if (executableValidator == null) {
        	executableValidator = Validation.byProvider(HibernateValidator.class)
                    .configure()
                    .failFast(true)
                    .parameterNameProvider(new ParanamerParameterNameProvider())
                    .buildValidatorFactory().getValidator().forExecutables();
        }
    }

    public Object aroundAdvice(ProceedingJoinPoint pjp) throws Throwable {
        // 方法参数校验
        MethodSignature ms = (MethodSignature) pjp.getSignature();
        Method method = ms.getMethod();
        Object target = pjp.getTarget();
        Object[] args = pjp.getArgs();
        Set<ConstraintViolation<Object>> violations = executableValidator.validateParameters(target, method, args);
        if (!violations.isEmpty()) {
            throw new YYException(PayRspCodeEnum.COMMON_ERROR_PARAMETER_INVALID, getViolationMsg(violations));
        }

        Object retVal = pjp.proceed();
        return retVal;
    }

    private String getViolationMsg(Set<ConstraintViolation<Object>> violations) {
        StringBuilder sb = new StringBuilder();
        Iterator<ConstraintViolation<Object>> iter = violations.iterator();
        while (iter.hasNext()) {
            ConstraintViolation<Object> cv = iter.next();
            String argsName = cv.getPropertyPath().toString();
            sb.append(argsName);
            sb.append(cv.getMessage());
            if (iter.hasNext()) {
                sb.append(",");
            }
        }
        return sb.toString();
    }
}

